package com.kitty.cross.core.codec;

import com.kitty.mina.codec.CodecContext;
import com.kitty.mina.codec.IMessageDecoder;
import com.kitty.mina.codec.SerializerHelper;
import com.kitty.mina.message.Message;
import com.kitty.mina.session.SessionManager;
import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.session.AttributeKey;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.CumulativeProtocolDecoder;
import org.apache.mina.filter.codec.ProtocolDecoderOutput;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class CrossMessageDecoder extends CumulativeProtocolDecoder {



    /** 编码上下文 */
    AttributeKey CODEC_CONTEXT = new AttributeKey(CrossMessageDecoder.class, "CONTEXT_KEY");

    @Override
    protected boolean doDecode(IoSession session, IoBuffer in, ProtocolDecoderOutput protocolDecoderOutput) throws Exception {
        // 必须保证每一个数据包的字节缓存都和session绑定在一起，不然就读取不了上一次剩余的数据了
        CodecContext context = SessionManager.INSTANCE.getSessionAttr(session, CODEC_CONTEXT,
                CodecContext.class);
        if (context == null) {
            context = new CodecContext();
            session.setAttribute(CODEC_CONTEXT, context);
        }

        IoBuffer ioBuffer = context.getBuffer();
        ioBuffer.put(in);

        IMessageDecoder msgDecoder = SerializerHelper.getInstance().getDecoder();

        // 在循环里迭代，以处理数据粘包
        for (; ; ) {
            ioBuffer.flip();
            // 消息元信息常量3表示消息body前面的两个字段，一个short表示module，一个byte表示cmd,
            final int metaSize = 3;
            if (ioBuffer.remaining() < metaSize) {
                ioBuffer.compact();
                return false;
            }
            // ----------------消息协议格式-------------------------
            // packetLength | moduleId | cmd  | body
            // int            short      byte byte[]
            int length = ioBuffer.getInt();
            // int packLen = length + metaSize;
            // 大于消息body长度，说明至少有一条完整的message消息
            if (ioBuffer.remaining() >= length) {
                int moduleId = ioBuffer.getInt();
                int msgbodyLen = length - metaSize;
                byte[] body = new byte[msgbodyLen];
                ioBuffer.get(body);
                Message msg = msgDecoder.readMessage(moduleId, (short) 0, body);

                protocolDecoderOutput.write(msg);
                if (ioBuffer.remaining() == 0) {
                    ioBuffer.clear();
                    break;
                }
                ioBuffer.compact();
            } else {
                // 数据包不完整，继续等待数据到达
                ioBuffer.rewind();
                ioBuffer.compact();
                break;
            }
        }

        return true;
    }

    @Override
    public void dispose(IoSession arg0) throws Exception {

    }

    @Override
    public void finishDecode(IoSession arg0, ProtocolDecoderOutput arg1) throws Exception {

    }
}
